////////////////////////////////////////////////////////////////////////////////
/*! \file
 * \brief Memory implementation file for the output-object.
 * \author Ivo Wingelaar
 * \date 2011
 * \version 0.1.0
 * \copyright GNU Lesser General Public License v3
 */
////////////////////////////////////////////////////////////////////////////////

#include "MythMemory_OutputMemory_C.hpp"

namespace Myth
{
namespace Memory
{

////////////////////////////////////////////////////////////////////////////////
//! Creates an output to a memory location.
OutputMemory_C::OutputMemory_C(const std::string& stream_name, void* memory, uintptr_t size, bool own_memory) :
    Output(stream_name),
    mMemory(memory),
    mSize(size),
    mPos(0),
    mOwnMemory(own_memory)
{
    //
}

////////////////////////////////////////////////////////////////////////////////
//! Virtual destructor.
OutputMemory_C::~OutputMemory_C(void)
{
    if(mOwnMemory)
        delete [] (char*)mMemory;
}

////////////////////////////////////////////////////////////////////////////////
//! Writes a number of bytes to an output.
uintptr_t OutputMemory_C::write(const void* buffer, uintptr_t size)
{
    int32_t amount = static_cast<int32_t>(size);
    if (mPos + amount > mSize)
        amount -= mPos + amount - mSize;

    if (amount <= 0)
        return 0;

    char* p = (char*)mMemory;
    memcpy(p + mPos, buffer, amount);

    mPos += amount;

    return amount;
}

////////////////////////////////////////////////////////////////////////////////
//! Changes the position in the data-output.
bool OutputMemory_C::seek(uintptr_t position, bool relative)
{
    if(relative)
    {
        if(mPos + position > mSize)
            return false;
        mPos += position;
    }
    else
    {
        if(position > mSize)
            return false;
        mPos = position;
    }

    return true;
}

////////////////////////////////////////////////////////////////////////////////
//! Returns the current position of the output.
uintptr_t OutputMemory_C::get_pos(void) const
{
    return mPos;
}

} // namespace Memory
} // namespace Myth
